package main

import (
	"fmt"
	"reflect"
)

func main() {
	str1 := "Hello, World!"
	str2 := "Go语音"
	// reflect.TypeOf().Kind() 可以知道某个变量的类型，
	//我们可以看到，字符串是以 byte 数组形式保存的，类型是 uint8，占1个 byte，打印时需要用 string 进行类型转换，
	//否则打印的是编码值
	fmt.Println(reflect.TypeOf(str2[2]).Kind()) // uint8
	fmt.Println(str1[2], string(str1[2]))       // 108 l
	fmt.Println(str2[2], string(str2[2]))       // 232 è
	fmt.Printf("%d %c\n", str2[2], str2[2])     // 232 è
	fmt.Println("len(str2)：", len(str2))        // len(str2)： 8
	runeArr := []rune(str2)
	fmt.Println(reflect.TypeOf(runeArr[2]).Kind()) // int32
	fmt.Println(runeArr[2], string(runeArr[2]))    // 35821 语

	arr := [5]int{1, 2, 3, 4, 5}
	for i := 0; i < len(arr); i++ {
		arr[i] += 100
	}
	fmt.Println(arr) // [101 102 103 104 105]

	//slice1 := make([]float32, 0) // 长度为0的切片
	slice2 := make([]float32, 3, 5)       // [0 0 0] 长度为3容量为5的切片
	fmt.Println(len(slice2), cap(slice2)) // 3 5

	// 添加元素，切片容量可以根据需要自动扩展
	slice2 = append(slice2, 1, 2, 3, 4)   // [0, 0, 0, 1, 2, 3, 4]
	fmt.Println(len(slice2), cap(slice2)) // 7 12

	// 子切片 [start, end)
	sub1 := slice2[3:] // [1 2 3 4]
	sub2 := slice2[:3] // [0 0 0]
	//sub3 := slice2[1:4] // [0 0 1]
	// 合并切片
	combined := append(sub1, sub2...) // [1, 2, 3, 4, 0, 0, 0]
	fmt.Println(combined)

	str := "Golang"
	//指针即某个值的地址，类型定义时使用符号*，
	//对一个已经存在的变量，使用 & 获取该变量的地址。
	var p *string = &str // p 是指向 str 的指针
	*p = "Hello"
	fmt.Println(str) // Hello 修改了 p，str 的值也发生了改变

	num := 100
	add(num)
	fmt.Println(num) // 100，num 没有变化

	realAdd(&num)
	fmt.Println(num) // 101，指针传递，num 被修改

	//流程控制(if, for, switch)
	age := 18
	if age < 18 {
		fmt.Printf("Kid")
	} else {
		fmt.Printf("Adult")
	}

	// switch
	type Gender int8
	const (
		MALE   Gender = 1
		FEMALE Gender = 2
	)

	gender := MALE

	switch gender {
	case FEMALE:
		fmt.Println("female")
	case MALE:
		fmt.Println("male")
	default:
		fmt.Println("unknown")
	}
}

// 一般来说，指针通常在函数传递参数，或者给某个类型定义新的方法时使用。
func add(num int) {
	num += 1
}

func realAdd(num *int) {
	*num += 1
}
